﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Remoting.Contexts;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Scheduler
{
    public class Worker
    {
        private readonly int _id;
        public string Name => $"Worker:{_id}";

        private readonly List<Middleware> _middleware = new List<Middleware>();
        private readonly WorkerTaskScheduler _workerTaskScheduler = new WorkerTaskScheduler();



        public Worker(int id)
        {
            _id = id;
            Buffer = new ConcurrentQueue<WorkerHandleResult>();
        }

        public void AddMiddleware(Middleware middleware)
        {
            Debug.Assert(middleware != null);
            _middleware.Add(middleware); //TODO 优先事项 
        }

        public Task Run(Context cxt)
        {
            try
            {


                Task t = new Task(() =>
                {

                    EmitEvent(cxt, new EventArgs(EventId.Init, _id));

                    while (!cxt.UserCancelled)
                    {
                        EmitEvent(cxt, new EventArgs(EventId.PassBegin, _id));

                        var value = cxt.LoadPass(_id, EventId.PassBegin);


                        var next = cxt.Next(_id);
                     

                        //Console.WriteLine($"st:{_id}=>EmitEvent {value}");
                        EmitEvent(cxt, new EventArgs(EventId.Handle, _id, next, value));


                        EmitEvent(cxt, new EventArgs(EventId.PassEnd, _id));
                        cxt.UnloadPass(_id, EventId.PassEnd, value);
                    }
                    EmitEvent(cxt, new EventArgs(EventId.Cleanup, _id));

                });

                t.Start(_workerTaskScheduler);
                return t;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
     

        }
        [DebuggerStepThrough]
        public void EmitEvent(Context ctx, EventArgs args)
        {
            foreach (var m in _middleware)
                m.HandleEvent(ctx, args);
        }


        public ConcurrentQueue<WorkerHandleResult> Buffer { get; }
        public bool HasInBuffer()
        {
            return Buffer.Count > 0;
        }

        public void AddToBuffer(WorkerHandleResult whr)
        {
            //  Debug.Assert(Buffer.Count != 1);

            Buffer.Enqueue(whr);
        }
        private void PrintDebugInfo()
        {
            Console.WriteLine();
        }


        public bool SkipThisPass(Context context)
        {
            return false;
        }
    }
}